import 'package:flutter_app/config/env.dart';
import 'package:http/http.dart' as http;
import 'package:logger/logger.dart';
import 'dart:convert';

class HttpUtil {
  static final HttpUtil _instance = HttpUtil._internal();
  factory HttpUtil() => _instance;

  final String baseUrl = Environment.apiUrl; // 设置你的基础URL
  final Duration timeout = const Duration(seconds: 30);

  final Logger _logger = Logger(
    printer: PrettyPrinter(
      methodCount: 0,
      errorMethodCount: 5,
      lineLength: 75,
      colors: true,
      printEmojis: true,
      printTime: true,
    ),
  );

  // 默认请求头
  final Map<String, String> _defaultHeaders = {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
  };

  HttpUtil._internal();

  // GET 请求
  Future<dynamic> get(
    String path, {
    Map<String, String>? headers,
    Map<String, dynamic>? queryParameters,
  }) async {
    final url = '$baseUrl$path';
    _logRequest('GET', url, headers: headers, queryParameters: queryParameters);

    try {
      final Uri uri = queryParameters != null
          ? Uri.parse(url).replace(queryParameters: queryParameters)
          : Uri.parse(url);

      final response = await http.get(
        uri,
        headers: {..._defaultHeaders, ...?headers},
      ).timeout(timeout);

      _logResponse(response);
      return _handleResponse(response);
    } catch (e) {
      _logError(e);
      throw _handleError(e);
    }
  }

  // POST 请求
  Future<dynamic> post(
    String path, {
    Map<String, String>? headers,
    dynamic body,
    Map<String, dynamic>? queryParameters,
  }) async {
    final url = '$baseUrl$path';
    _logRequest('POST', url,
        headers: headers, body: body, queryParameters: queryParameters);

    try {
      final Uri uri = queryParameters != null
          ? Uri.parse(url).replace(queryParameters: queryParameters)
          : Uri.parse(url);

      final response = await http
          .post(
            uri,
            headers: {..._defaultHeaders, ...?headers},
            body: body != null ? jsonEncode(body) : null,
          )
          .timeout(timeout);

      _logResponse(response);
      return _handleResponse(response);
    } catch (e) {
      _logError(e);
      throw _handleError(e);
    }
  }

  // PUT 请求
  Future<dynamic> put(
    String url, {
    Map<String, String>? headers,
    dynamic body,
    Map<String, dynamic>? queryParameters,
  }) async {
    try {
      final Uri uri = queryParameters != null
          ? Uri.parse(url).replace(queryParameters: queryParameters)
          : Uri.parse(url);

      final response = await http.put(
        uri,
        headers: {..._defaultHeaders, ...?headers},
        body: body != null ? jsonEncode(body) : null,
      );
      return _handleResponse(response);
    } catch (e) {
      throw _handleError(e);
    }
  }

  // DELETE 请求
  Future<dynamic> delete(
    String url, {
    Map<String, String>? headers,
    Map<String, dynamic>? queryParameters,
  }) async {
    try {
      final Uri uri = queryParameters != null
          ? Uri.parse(url).replace(queryParameters: queryParameters)
          : Uri.parse(url);

      final response = await http.delete(
        uri,
        headers: {..._defaultHeaders, ...?headers},
      );
      return _handleResponse(response);
    } catch (e) {
      throw _handleError(e);
    }
  }

  // 处理响应
  dynamic _handleResponse(http.Response response) {
    if (response.statusCode >= 200 && response.statusCode < 300) {
      try {
        // 使用 utf8 解码响应数据
        final decodedBody = utf8.decode(response.bodyBytes);
        return jsonDecode(decodedBody);
      } catch (e) {
        // 如果不是 JSON 数据，直接返回解码后的字符串
        return utf8.decode(response.bodyBytes);
      }
    } else {
      throw _createHttpException(response);
    }
  }

  // 创建HTTP异常
  HttpException _createHttpException(http.Response response) {
    String message;
    switch (response.statusCode) {
      case 400:
        message = '请求参数错误';
        break;
      case 401:
        message = '未授权，请重新登录';
        break;
      case 403:
        message = '拒绝访问';
        break;
      case 404:
        message = '请求地址不存在';
        break;
      case 500:
        message = '服务器内部错误';
        break;
      default:
        message = '网络错误(${response.statusCode})';
    }
    return HttpException(message, response: response);
  }

  // 处理错误
  Exception _handleError(dynamic error) {
    if (error is HttpException) return error;
    if (error is TimeoutException) {
      return HttpException('网络连接超时，请检查网络设置');
    }
    return HttpException('网络错误，请稍后重试: $error');
  }

  // 日志记录
  void _logRequest(
    String method,
    String url, {
    Map<String, String>? headers,
    dynamic body,
    Map<String, dynamic>? queryParameters,
  }) {
    _logger.i('REQUEST[$method] => PATH: $url');
    _logger.i('Headers: ${headers ?? _defaultHeaders}');
    if (body != null) _logger.i('Body: $body');
    if (queryParameters != null)
      _logger.i('Query Parameters: $queryParameters');
  }

  void _logResponse(http.Response response) {
    _logger.i(
        'RESPONSE[${response.statusCode}] => PATH: ${response.request?.url}');
    _logger.i('Response Body: ${response.body}');
  }

  void _logError(dynamic error) {
    _logger.e('ERROR: $error');
  }
}

class HttpException implements Exception {
  final String message;
  final http.Response? response;

  HttpException(this.message, {this.response});

  @override
  String toString() => message;
}

class TimeoutException implements Exception {
  final String message;
  TimeoutException([this.message = '请求超时']);

  @override
  String toString() => message;
}
